package cn.janyd.jmall.system.manager.admin;

import cn.hutool.core.lang.UUID;
import cn.janyd.common.core.util.EncryptUtil;
import cn.janyd.common.core.util.ServiceExceptionUtil;
import cn.janyd.jmall.system.constants.SystemErrorCode;
import cn.janyd.jmall.system.convert.AdminConverter;
import cn.janyd.jmall.system.dal.db.dataobject.AdminDO;
import cn.janyd.jmall.system.dal.db.mapper.AdminMapper;
import cn.janyd.jmall.system.dal.db.mapper.DepartmentMapper;
import cn.janyd.jmall.system.enums.AdminStatus;
import cn.janyd.jmall.system.manager.admin.bo.AdminCreateReqBo;
import cn.janyd.jmall.system.manager.admin.bo.AdminUpdateBO;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Objects;

import static cn.janyd.jmall.system.constants.SystemErrorCode.ACCOUNT_DISABLED;
import static cn.janyd.jmall.system.constants.SystemErrorCode.USERNAME_OR_PASSWORD_ERROR;

/**
 * @author Janyd
 * @since 2020-08-15 16:20
 */
@Service
@AllArgsConstructor
public class AdminManager {

    private final AdminMapper adminMapper;

    private final DepartmentMapper departmentMapper;

    /**
     * 创建管理员
     *
     * @param adminCreateReq 创建管理员信息
     * @return 管理员信息
     */
    public AdminDO createAdmin(AdminCreateReqBo adminCreateReq) {
        if (departmentMapper.selectById(adminCreateReq.getDepartmentId()) == null) {
            throw ServiceExceptionUtil.exception(SystemErrorCode.DEPARTMENT_NOT_EXITS);
        }

        if (adminMapper.selectCountByEmail(adminCreateReq.getEmail()) > 0) {
            throw ServiceExceptionUtil.exception(SystemErrorCode.EMAIL_IS_EXITS);
        }

        if (adminMapper.selectCountByUsername(adminCreateReq.getUsername()) > 0) {
            throw ServiceExceptionUtil.exception(SystemErrorCode.USERNAME_IS_EXITS);
        }

        AdminDO adminDO = AdminConverter.INSTANCE.convert(adminCreateReq);

        String salt = genPasswordSalt();
        String password = adminCreateReq.getPassword();

        if (StringUtils.isBlank(password)) {
            password = genPassword();
        }

        password = encodePassword(password, salt);

        adminDO.setPassword(password)
                .setSalt(salt);

        adminMapper.insert(adminDO);


        return adminDO;
    }

    /**
     * 更新管理员信息
     *
     * @param adminUpdateBO 管理员信息
     */
    public void updateAdmin(AdminUpdateBO adminUpdateBO) {
        AdminDO adminDO = adminMapper.selectById(adminUpdateBO.getId());
        if (adminDO == null) {
            throw ServiceExceptionUtil.exception(SystemErrorCode.ADMIN_NOT_EXITS);
        }

        //邮箱校验
        if (StringUtils.isNotBlank(adminUpdateBO.getEmail())
                && !Objects.equals(adminUpdateBO.getEmail(), adminDO.getEmail())) {
            if (adminMapper.selectCountByEmail(adminUpdateBO.getEmail()) > 0) {
                throw ServiceExceptionUtil.exception(SystemErrorCode.EMAIL_IS_EXITS);
            } else {
                adminDO.setEmail(adminUpdateBO.getEmail());
            }
        }

        //部门
        if (adminUpdateBO.getDepartmentId() != null && adminUpdateBO.getDepartmentId() > 0) {
            if (departmentMapper.selectById(adminUpdateBO.getDepartmentId()) == null) {
                throw ServiceExceptionUtil.exception(SystemErrorCode.DEPARTMENT_NOT_EXITS);
            }
        }

        //头像
        if (StringUtils.isNotBlank(adminUpdateBO.getAvatar())) {
            adminDO.setAvatar(adminUpdateBO.getAvatar());
        }

        //用户名
        if (StringUtils.isNotBlank(adminUpdateBO.getUsername())) {
            if (adminMapper.selectCountByUsername(adminUpdateBO.getUsername()) > 0) {
                throw ServiceExceptionUtil.exception(SystemErrorCode.USERNAME_IS_EXITS);
            } else {
                adminDO.setUsername(adminUpdateBO.getUsername());
            }
        }

        if (StringUtils.isNotBlank(adminUpdateBO.getPassword())) {
            String salt = genPasswordSalt();
            String password = adminUpdateBO.getPassword();

            password = encodePassword(password, salt);

            adminDO.setPassword(password).setSalt(salt);
        }

        if (adminUpdateBO.getStatus() != null) {
            adminDO.setStatus(adminUpdateBO.getStatus());
        }

        adminMapper.updateById(adminDO);
    }

    /**
     * 校验用户名密码
     *
     * @param username 用户名
     * @param password 密码
     * @param ip       ip
     * @return 管理员信息
     */
    public AdminDO verifyPassword(String username, String password, String ip) {
        AdminDO adminDO = adminMapper.selectByUsername(username);
        if (adminDO == null) {
            throw ServiceExceptionUtil.exception(USERNAME_OR_PASSWORD_ERROR);
        }

        if (!Objects.equals(encodePassword(password, adminDO.getSalt()), adminDO.getPassword())) {
            throw ServiceExceptionUtil.exception(USERNAME_OR_PASSWORD_ERROR);
        }

        if (adminDO.getStatus() == AdminStatus.INACTIVE) {
            throw ServiceExceptionUtil.exception(ACCOUNT_DISABLED);
        }

        return adminDO;
    }

    private String genPasswordSalt() {
        return EncryptUtil.genBcryptSalt();
    }

    private String genPassword() {
        return UUID.fastUUID().toString(true);
    }

    private String encodePassword(String password, String salt) {
        return EncryptUtil.encrypt(password, salt);
    }
}
